package org.dandsoft.blackbox.snn.study;

import org.dandsoft.blackbox.snn.Trigger;
import org.dandsoft.blackbox.snn.Environment;
import org.dandsoft.blackbox.snn.Signal;

/**
 * @author Vilyuzhanin Denis (Fin)
 */
public class Teacher {

    /**
     * <p>
     * Обучаем триггер. В зависимости от текущей фазы обучения, выполняются различные способы обучения.
     * Если текущая фаза не соответствует действительным результатам, то принимается решение об изменении
     * стадии под более подходящую.
     * </p>
     * <p>
     * Если параметр trigger содержит триггер с фазой обучения N, то принимается решение об его дальнейшей фазе обучения.
     * Метод {@link org.dandsoft.blackbox.snn.study.Teacher#getXRequiredNewTriggers(org.dandsoft.blackbox.snn.Environment)}
     * возвращает количество новых триггеров для которых можно придумать X. Это значение должно определяться на основании
     * наблюдений и анализе закономерностей.
     * </p>
     *
     * @param environment
     * @param trigger
     */
    public void study(Environment environment, Trigger trigger) {
        if (StudyPhase.N == trigger.getStudyStatus().getStudyPhase()) {
            //можно придумать X, Y, или F                     
            if (getXRequiredNewTriggers(environment) > 0) {
                //придумать X
                studyX(environment, trigger);
            }
        } else if (StudyPhase.X == trigger.getStudyStatus().getStudyPhase()) {
            if (trigger.getStudyStatus().isCorrectStatus()) {
                //проконтролировать корректность состояния
                checkX(environment, trigger);
            } else {
                //решить какой компонент придумать F или Y
            }
        }
    }

    public void studyX(Environment environment, Trigger trigger) {
        if (studyUseless(environment, trigger)) {
            return;
        }
        if (studyActiveGroups(environment, trigger)) {
            return;
        }

    }

    /**
     * <p>
     * Контроль корректности состояния X. Необходимо чтобы найденный образ можно было считать коректным.
     * Вопервых он должен быть действительно явлением. А не просто случайным скоплением, которое больше не повториться.
     * Какой от него толк если на него нельзя отреагировать. Значит можно говорить о параметрах контролирующих качество
     * образа.
     * </p>
     * <ul>
     * <li>
     * <b>Время</b> - время которое явление наблюдалось без изменений. Если оно наблюдалось дольше или меньше,
     * то это другой сигнал. Необходимо контролировать время активности сигнала
     * </li>
     * <li>
     * <b>Количество повторений</b> - сколько раз данное явление наблюдалос. Если такое явление было замечено
     * всего несколько раз. Можно ли говорить о том, что оно еще повториться.
     * /li>
     * </ul>
     *
     * @param environment
     * @param trigger
     */
    public void checkX(Environment environment, Trigger trigger) {
        
    }

    public int getRequiredNewTriggers(Environment environment) {
        int result = 0;
        if (environment.getUseless().size() > 1) {
            result += getXRequiredNewTriggers(environment);
        }
        return result;
    }

    protected int getXRequiredNewTriggers(Environment environment) {
        if (environment.getUseless().size() > 1) {
            return 1;
        } else {
            return 0;
        }
    }

    /**
     * <p>
     * Создать новый триггер из неиспользованных сигналов. Эта операция относиться
     * к N-X цепеочке. Мы придумываем набор аргументов.
     * </p>
     */
    protected boolean studyUseless(Environment environment, Trigger newTrigger) {
        if (environment.getUseless().size() > 1) {
            for (Signal useless : environment.getUseless()) {
                newTrigger.connect(useless.getSignalId(), useless.getValue());
            }
            newTrigger.getStudyStatus().setStudyPhase(StudyPhase.X);
            newTrigger.getStudyStatus().setCorrectStatus(false);
            return true;
        }
        return false;
    }

    protected boolean studyActiveGroups(Environment environment, Trigger trigger) {
        return false;
    }
}
